package cn.anlab.anappframe.system;

import java.lang.ref.SoftReference;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.app.ActivityManager;
import android.app.Application;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.WindowManager;
import android.widget.ListView;
import android.widget.Toast;
import cn.anlab.anappframe.BaseActivity;
import cn.anlab.anappframe.R;
import cn.anlab.anappframe.net.IClient;
import cn.anlab.anappframe.net.IOClient;
import cn.anlab.anappframe.net.IOErrorListener;
import cn.anlab.anappframe.net.JsonIOHandler;
import cn.anlab.anappframe.net.Packet;
import cn.anlab.anappframe.net.ReceiveCallback;

public class CoreApplication extends Application {

	private static final String tag = "anlog";

	public static CoreApplication application;

	private static String hostname = "192.168.1.100"; // 192.168.8.66
	private static int port = 8899;
	private static int THREAD_POOL_SIZE = 3;

	private IClient<Packet> conn;

	/**
	 * key为感兴趣的命令(接收到的cmd)， value为回调处理的handler
	 */
	private ConcurrentMap<Integer, Set<Handler>> handlerMap;

	/**
	 * 接口类软件引用，key为类名， value为Object对象
	 */
	public SoftReference<Map<String, Object>> interObjMapRef;

	public ExecutorService asyncRunTaskPool;

	/**
	 * Channel
	 */
	public int currentChannel;
	
	public static IClient<Packet> getConnection() {
		return application.conn;
	}
	
	public static Map<String, Object>getInterObjMap() {
		return application.interObjMapRef.get();
	}

	public static ExecutorService getAsyncRunTaskPool() {
		return application.asyncRunTaskPool;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.d("anlog", "CoreApplication.onCreate()");
		application = this;

		// 客户端接收到服务端数据的处理handler集
		handlerMap = new ConcurrentHashMap<Integer, Set<Handler>>();

		// 接口对象类软件引用
		Map<String, Object> interObjMap = new HashMap<String, Object>();
		interObjMapRef = new SoftReference<Map<String, Object>>(interObjMap);

		// 异步任务线程池
		asyncRunTaskPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

//		registerHandler(Event.EXCEPTION, appHandler);

		java.lang.System.setProperty("java.net.preferIPv4Stack", "true");
		java.lang.System.setProperty("java.net.preferIPv6Addresses", "false");

	}
	
	/**
	 * 初始化网络连接
	 */
	public static void initNetConnection() {
		application.conn = new IOClient<Packet>();
		application.conn.setProtocolHandler(new JsonIOHandler());
		application.conn.setIoErrorListener(application.ioErrorListener);
		application.conn.setReceiveCallback(application.receiveCallback);
		application.conn.connect(hostname, port);
	}
	
	/**
	 * 向远程服务器发送数据
	 * @param cmd
	 * @param data
	 */
	public static void sendRemote(int cmd, Object data) {
		if( ! application.conn.isConnected()) {
			application.conn.connect(hostname, port);
		}
		Packet p = new Packet(cmd, data);
		application.conn.send(p);
	}
	
	/**
	 * 切换通道
	 * @see R.array.channels
	 */
	public static void changeChannel(String channelCode) {
		
		// 国际化
		Locale locale = new Locale(channelCode);
		Locale.setDefault(locale);
		Configuration config = new Configuration();
		config.locale = locale;
		application.getBaseContext().getResources().updateConfiguration(config, null);
	}

	
	private Handler appHandler = new Handler() {
		public void handleMessage(Message msg) {
			Toast.makeText(CoreApplication.this, "[e]" + msg.obj, Toast.LENGTH_SHORT).show();
		};
	};

	/**
	 * 注册Handler <br />
	 * 服务端发来数据时，根据interestEvent来选择由哪些handler来处理界面的展示
	 * 
	 * @param interestEvent
	 * @param handler
	 * @see Event
	 */
	public static void registerHandler(int interestEvent, Handler handler) {
		Integer eventKey = new Integer(interestEvent);
		if (!application.handlerMap.containsKey(eventKey)) {
			application.handlerMap.put(eventKey, new HashSet<Handler>());
		}
		Set<Handler> handlerSet = application.handlerMap.get(eventKey);
		if (!handlerSet.contains(handler)) {
			Log.i(tag, "register event = " + interestEvent + ", handler = " + handler.toString());
			handlerSet.add(handler);
		}
	}

	/**
	 * 分发响应
	 * 
	 * @param cmd
	 *            感兴趣的事件，即服务端发过来的cmd命令编码
	 * @see Event
	 */
	private void dispatchResponse(int cmd, Object data) {
		Set<Handler> handlerSet = handlerMap.get(new Integer(cmd));
		if (handlerSet != null && handlerSet.size() > 0) {
			// 遍历每一个Handler，发消息
			for (Handler h : handlerSet) {
				Message msg = new Message();
				msg.what = cmd;
				msg.obj = data;
				h.sendMessage(msg);
			}
		} else {
			Log.w(tag, "not found handler with eventKey = " + cmd);
		}
		
	}

	/**
	 * IO错误监听
	 */
	private IOErrorListener ioErrorListener = new IOErrorListener() {
		@Override
		public void onError(int errorCode, Exception e) {
			if(errorCode == CONNECT_TIMEOUT || errorCode == IO_EXCEPTION) {
				application.conn.disconnect();
			}
			Log.e(tag, "IOErrorListener.onError = " + e);
			Message msg = new Message();
			msg.what = Event.EXCEPTION;
			msg.obj = e;
			appHandler.sendMessage(msg);
		};
	};

	/**
	 * 回调处理，监听服务端发来的数据
	 */
	private ReceiveCallback<Packet> receiveCallback = new ReceiveCallback<Packet>() {
		@Override
		public void onReceive(InetSocketAddress from, Packet p) {
			Log.e("CoreApplication", "from : " + from + ", receive : " + p);
			int cmd = p.getCmd();
			Object data = p.getData();
			dispatchResponse(cmd, data);
		}
	};

	@Override
	public void onTerminate() {
		super.onTerminate();
		Log.d("anlog", "CoreApplication.onTerminate()");
	}

}
